package com.nx.platform.es.biz.query.agg;

import com.google.common.base.Preconditions;
import com.nx.platform.es.entity.response.TermsAggResult;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author
 * @since 2016年10月21日
 */
public class AggResponses {

    private AggRequestContext context;
    private SearchResponse response;

    private AggResponses() {}

    public static AggResponses create(AggRequestContext context, SearchResponse response) {
        AggResponses r = new AggResponses();
        r.response = response;
        r.context = context;
        return r;
    }

    public <T> T to(AggResponseConverter<T> converter, T defaultValue) {
        if (response != null) {
            return converter.convert(context, response);
        } else {
            return defaultValue;
        }
    }

    public TermsAggResult toTermsAggResult() {
        return to(AggResultConverter.INSTANCE, new TermsAggResult());
    }

    public enum AggResultConverter implements AggResponseConverter<TermsAggResult> {
        INSTANCE;

        @Override
        public TermsAggResult convert(AggRequestContext context, SearchResponse response) {
            Preconditions.checkNotNull(response, "response is null");
            int totalHits = (int) response.getHits().getTotalHits();
            ParsedLongTerms agg = response.getAggregations().get("default");
            List<? extends Terms.Bucket> bucketList = agg.getBuckets();
            if (bucketList.isEmpty()) {
                return new TermsAggResult(totalHits);
            }
            LinkedHashMap<String, Long> buckets = new LinkedHashMap<>(bucketList.size());
            for (Terms.Bucket bucket : bucketList) {
                buckets.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
            return new TermsAggResult(totalHits, buckets);
        }
    }

    public interface AggResponseConverter<T> {
        T convert(AggRequestContext context, SearchResponse response);
    }

}
